/**
 * Avatar Utility Functions
 * Helper functions for avatar data management, storage, and validation
 */

import { AvatarConfig, AVATAR_OPTIONS, DEFAULT_AVATAR_CONFIG } from './avatar-models.js';

/**
 * Avatar Storage Manager
 * Handles local storage operations for avatar configurations
 */
export class AvatarStorageManager {
  static STORAGE_KEY = 'user_avatar_config';
  static TEMP_STORAGE_KEY = 'temp_avatar_config';

  /**
   * Save avatar configuration to local storage
   */
  static async saveAvatarConfig(avatarConfig) {
    try {
      const configData = avatarConfig.toJSON();
      await wx.setStorage({
        key: this.STORAGE_KEY,
        data: configData
      });
      return { success: true };
    } catch (error) {
      console.error('Failed to save avatar config:', error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Load avatar configuration from local storage
   */
  static async loadAvatarConfig() {
    try {
      const result = await wx.getStorage({
        key: this.STORAGE_KEY
      });
      return {
        success: true,
        config: AvatarConfig.fromJSON(result.data)
      };
    } catch (error) {
      console.log('No saved avatar config found, using default');
      return {
        success: true,
        config: new AvatarConfig()
      };
    }
  }

  /**
   * Save temporary avatar configuration (for editing)
   */
  static async saveTempAvatarConfig(avatarConfig) {
    try {
      const configData = avatarConfig.toJSON();
      await wx.setStorage({
        key: this.TEMP_STORAGE_KEY,
        data: configData
      });
      return { success: true };
    } catch (error) {
      console.error('Failed to save temp avatar config:', error);
      return { success: false, error: error.message };
    }
  }

  /**
   * Load temporary avatar configuration
   */
  static async loadTempAvatarConfig() {
    try {
      const result = await wx.getStorage({
        key: this.TEMP_STORAGE_KEY
      });
      return {
        success: true,
        config: AvatarConfig.fromJSON(result.data)
      };
    } catch (error) {
      return { success: false, error: 'No temp config found' };
    }
  }

  /**
   * Clear temporary avatar configuration
   */
  static async clearTempAvatarConfig() {
    try {
      await wx.removeStorage({
        key: this.TEMP_STORAGE_KEY
      });
      return { success: true };
    } catch (error) {
      return { success: false, error: error.message };
    }
  }
}

/**
 * Avatar Validation Utilities
 */
export class AvatarValidator {
  /**
   * Validate avatar configuration with detailed feedback
   */
  static validateConfiguration(config) {
    const avatarConfig = config instanceof AvatarConfig ? config : new AvatarConfig(config);
    const validation = avatarConfig.validate();
    
    return {
      ...validation,
      details: this.getValidationDetails(avatarConfig)
    };
  }

  /**
   * Get detailed validation information
   */
  static getValidationDetails(avatarConfig) {
    const details = {
      faceShape: this.validateFaceShape(avatarConfig.faceShape),
      hairstyle: this.validateHairstyle(avatarConfig.hairstyle),
      hairColor: this.validateHairColor(avatarConfig.hairColor),
      eyeShape: this.validateEyeShape(avatarConfig.eyeShape),
      clothing: this.validateClothing(avatarConfig.clothing),
      accessories: this.validateAccessories(avatarConfig.accessories)
    };

    return details;
  }

  static validateFaceShape(faceShape) {
    const isValid = AVATAR_OPTIONS.FACE_SHAPES.some(shape => shape.id === faceShape);
    return {
      isValid,
      message: isValid ? 'Valid face shape' : `Invalid face shape: ${faceShape}`,
      suggestions: isValid ? [] : AVATAR_OPTIONS.FACE_SHAPES.slice(0, 3).map(shape => shape.id)
    };
  }

  static validateHairstyle(hairstyle) {
    const isValid = AVATAR_OPTIONS.HAIRSTYLES.some(style => style.id === hairstyle);
    return {
      isValid,
      message: isValid ? 'Valid hairstyle' : `Invalid hairstyle: ${hairstyle}`,
      suggestions: isValid ? [] : AVATAR_OPTIONS.HAIRSTYLES.slice(0, 3).map(style => style.id)
    };
  }

  static validateHairColor(hairColor) {
    const isValid = AVATAR_OPTIONS.HAIR_COLORS.some(color => color.id === hairColor);
    return {
      isValid,
      message: isValid ? 'Valid hair color' : `Invalid hair color: ${hairColor}`,
      suggestions: isValid ? [] : AVATAR_OPTIONS.HAIR_COLORS.slice(0, 3).map(color => color.id)
    };
  }

  static validateEyeShape(eyeShape) {
    const isValid = AVATAR_OPTIONS.EYE_SHAPES.some(shape => shape.id === eyeShape);
    return {
      isValid,
      message: isValid ? 'Valid eye shape' : `Invalid eye shape: ${eyeShape}`,
      suggestions: isValid ? [] : AVATAR_OPTIONS.EYE_SHAPES.slice(0, 3).map(shape => shape.id)
    };
  }

  static validateClothing(clothing) {
    if (!clothing || typeof clothing !== 'object') {
      return {
        isValid: false,
        message: 'Clothing configuration is required',
        suggestions: ['casual', 'formal', 'dress']
      };
    }

    const { category, item, color } = clothing;
    
    // Check category
    if (!AVATAR_OPTIONS.CLOTHING[category?.toUpperCase()]) {
      return {
        isValid: false,
        message: `Invalid clothing category: ${category}`,
        suggestions: Object.keys(AVATAR_OPTIONS.CLOTHING).map(cat => cat.toLowerCase())
      };
    }

    // Check item
    const categoryItems = AVATAR_OPTIONS.CLOTHING[category.toUpperCase()];
    const itemExists = categoryItems.some(clothingItem => clothingItem.id === item);
    
    if (!itemExists) {
      return {
        isValid: false,
        message: `Invalid clothing item: ${item}`,
        suggestions: categoryItems.slice(0, 3).map(clothingItem => clothingItem.id)
      };
    }

    // Check color
    const clothingItem = categoryItems.find(clothingItem => clothingItem.id === item);
    const colorValid = clothingItem.colors.includes(color);
    
    if (!colorValid) {
      return {
        isValid: false,
        message: `Invalid color for ${item}: ${color}`,
        suggestions: clothingItem.colors.slice(0, 3)
      };
    }

    return {
      isValid: true,
      message: 'Valid clothing configuration'
    };
  }

  static validateAccessories(accessories) {
    if (!accessories || typeof accessories !== 'object') {
      return {
        isValid: false,
        message: 'Accessories configuration is required',
        suggestions: ['glasses', 'hat', 'jewelry', 'scarf']
      };
    }

    for (const [accessoryType, accessoryValue] of Object.entries(accessories)) {
      const accessoryOption = AVATAR_OPTIONS.ACCESSORIES.find(acc => acc.id === accessoryType);
      
      if (!accessoryOption) {
        return {
          isValid: false,
          message: `Invalid accessory type: ${accessoryType}`,
          suggestions: AVATAR_OPTIONS.ACCESSORIES.map(acc => acc.id)
        };
      }
      
      if (!accessoryOption.types.includes(accessoryValue)) {
        return {
          isValid: false,
          message: `Invalid ${accessoryType} value: ${accessoryValue}`,
          suggestions: accessoryOption.types.slice(0, 3)
        };
      }
    }

    return {
      isValid: true,
      message: 'Valid accessories configuration'
    };
  }
}

/**
 * Avatar Data Serialization Utilities
 */
export class AvatarSerializer {
  /**
   * Serialize avatar configuration for API transmission
   */
  static serializeForAPI(avatarConfig) {
    const config = avatarConfig instanceof AvatarConfig ? avatarConfig : new AvatarConfig(avatarConfig);
    
    return {
      avatar_config: {
        face_shape: config.faceShape,
        hairstyle: config.hairstyle,
        hair_color: config.hairColor,
        eye_shape: config.eyeShape,
        clothing: {
          category: config.clothing.category,
          item: config.clothing.item,
          color: config.clothing.color
        },
        accessories: {
          glasses: config.accessories.glasses,
          hat: config.accessories.hat,
          jewelry: config.accessories.jewelry,
          scarf: config.accessories.scarf
        },
        version: config.version
      },
      created_at: new Date().toISOString()
    };
  }

  /**
   * Deserialize avatar configuration from API response
   */
  static deserializeFromAPI(apiData) {
    try {
      const avatarConfig = apiData.avatar_config || apiData;
      
      return new AvatarConfig({
        faceShape: avatarConfig.face_shape,
        hairstyle: avatarConfig.hairstyle,
        hairColor: avatarConfig.hair_color,
        eyeShape: avatarConfig.eye_shape,
        clothing: {
          category: avatarConfig.clothing?.category,
          item: avatarConfig.clothing?.item,
          color: avatarConfig.clothing?.color
        },
        accessories: {
          glasses: avatarConfig.accessories?.glasses || 'none',
          hat: avatarConfig.accessories?.hat || 'none',
          jewelry: avatarConfig.accessories?.jewelry || 'none',
          scarf: avatarConfig.accessories?.scarf || 'none'
        },
        version: avatarConfig.version || '1.0'
      });
    } catch (error) {
      console.error('Failed to deserialize avatar config from API:', error);
      return new AvatarConfig(); // Return default configuration
    }
  }

  /**
   * Create compact representation for display
   */
  static createCompactRepresentation(avatarConfig) {
    const config = avatarConfig instanceof AvatarConfig ? avatarConfig : new AvatarConfig(avatarConfig);
    
    return {
      id: this.generateConfigHash(config),
      description: config.getDescription(),
      preview: {
        face: config.faceShape,
        hair: `${config.hairColor}_${config.hairstyle}`,
        eyes: config.eyeShape,
        outfit: `${config.clothing.category}_${config.clothing.item}_${config.clothing.color}`
      }
    };
  }

  /**
   * Generate unique hash for avatar configuration
   */
  static generateConfigHash(avatarConfig) {
    const config = avatarConfig instanceof AvatarConfig ? avatarConfig : new AvatarConfig(avatarConfig);
    const configString = JSON.stringify(config.toJSON());
    
    // Simple hash function for configuration identification
    let hash = 0;
    for (let i = 0; i < configString.length; i++) {
      const char = configString.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // Convert to 32-bit integer
    }
    
    return Math.abs(hash).toString(16);
  }
}

/**
 * Avatar Comparison Utilities
 */
export class AvatarComparator {
  /**
   * Compare two avatar configurations
   */
  static compareConfigurations(config1, config2) {
    const avatar1 = config1 instanceof AvatarConfig ? config1 : new AvatarConfig(config1);
    const avatar2 = config2 instanceof AvatarConfig ? config2 : new AvatarConfig(config2);
    
    const differences = [];
    
    if (avatar1.faceShape !== avatar2.faceShape) {
      differences.push({ property: 'faceShape', value1: avatar1.faceShape, value2: avatar2.faceShape });
    }
    
    if (avatar1.hairstyle !== avatar2.hairstyle) {
      differences.push({ property: 'hairstyle', value1: avatar1.hairstyle, value2: avatar2.hairstyle });
    }
    
    if (avatar1.hairColor !== avatar2.hairColor) {
      differences.push({ property: 'hairColor', value1: avatar1.hairColor, value2: avatar2.hairColor });
    }
    
    if (avatar1.eyeShape !== avatar2.eyeShape) {
      differences.push({ property: 'eyeShape', value1: avatar1.eyeShape, value2: avatar2.eyeShape });
    }
    
    // Compare clothing
    if (JSON.stringify(avatar1.clothing) !== JSON.stringify(avatar2.clothing)) {
      differences.push({ property: 'clothing', value1: avatar1.clothing, value2: avatar2.clothing });
    }
    
    // Compare accessories
    if (JSON.stringify(avatar1.accessories) !== JSON.stringify(avatar2.accessories)) {
      differences.push({ property: 'accessories', value1: avatar1.accessories, value2: avatar2.accessories });
    }
    
    return {
      identical: differences.length === 0,
      differences,
      similarityScore: this.calculateSimilarityScore(avatar1, avatar2)
    };
  }

  /**
   * Calculate similarity score between two avatars (0-100)
   */
  static calculateSimilarityScore(avatar1, avatar2) {
    const totalProperties = 6; // faceShape, hairstyle, hairColor, eyeShape, clothing, accessories
    let matchingProperties = 0;
    
    if (avatar1.faceShape === avatar2.faceShape) matchingProperties++;
    if (avatar1.hairstyle === avatar2.hairstyle) matchingProperties++;
    if (avatar1.hairColor === avatar2.hairColor) matchingProperties++;
    if (avatar1.eyeShape === avatar2.eyeShape) matchingProperties++;
    if (JSON.stringify(avatar1.clothing) === JSON.stringify(avatar2.clothing)) matchingProperties++;
    if (JSON.stringify(avatar1.accessories) === JSON.stringify(avatar2.accessories)) matchingProperties++;
    
    return Math.round((matchingProperties / totalProperties) * 100);
  }
}

/**
 * Avatar Migration Utilities
 * Handle version upgrades and data migration
 */
export class AvatarMigrator {
  /**
   * Migrate avatar configuration to latest version
   */
  static migrateToLatestVersion(avatarConfig) {
    const config = avatarConfig instanceof AvatarConfig ? avatarConfig.toJSON() : avatarConfig;
    const currentVersion = config.version || '1.0';
    
    // Add migration logic for future versions
    switch (currentVersion) {
      case '1.0':
        // Current version, no migration needed
        return new AvatarConfig(config);
      default:
        console.warn(`Unknown avatar config version: ${currentVersion}`);
        return new AvatarConfig(config);
    }
  }

  /**
   * Check if migration is needed
   */
  static needsMigration(avatarConfig) {
    const config = avatarConfig instanceof AvatarConfig ? avatarConfig.toJSON() : avatarConfig;
    const currentVersion = config.version || '1.0';
    const latestVersion = DEFAULT_AVATAR_CONFIG.version;
    
    return currentVersion !== latestVersion;
  }
}

// Export utility functions for easy access
export const avatarUtils = {
  storage: AvatarStorageManager,
  validator: AvatarValidator,
  serializer: AvatarSerializer,
  comparator: AvatarComparator,
  migrator: AvatarMigrator
};

export default avatarUtils;